package ru.susu.algebra.centralunits.alternating.initializers;

import java.math.BigInteger;
import java.util.Map;

import com.google.common.collect.Maps;

import ru.susu.algebra.centralunits.alternating.MathMethodWithInitializers;
import ru.susu.algebra.field.quadratic.QuadraticInteger;
import ru.susu.algebra.pair.Pair;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.properties.IPropertySource;

/**
 * @author akargapolov
 * @since: 07.09.2010
 */
public class BetaInitializer extends MathMethodWithInitializers<Object>
{
	private static final Class[] DEPENDENCIES = {SpecialRowsInitializer.class, QuadraticFieldsInitializer.class};

	private static final String BETA_MAP = "BetaMap";

	@Override
	protected Class[] getDependentInitializers()
	{
		return DEPENDENCIES;
	}

	/**
	 * Вычисление коэффициента перед беттой для конкретного характера и разбиения
	 * tr (char.a * w + char.b * w^2) = char.a + char.b * tr(w^2)
	 */
	private BigInteger calculateBeta(IPropertySource ps, Partition p, QuadraticInteger character) throws Exception
	{
		return character.getA().add(character.getB().multiply(QuadraticFieldsInitializer.getOmega2(ps, p).getTrace()));
	}

	@Override
	protected Object directRun(IPropertySource ps) throws Exception
	{
		if (ps.getValue(BETA_MAP) == null)
		{
			Map<Pair<Partition, QuadraticInteger>, BigInteger> map = Maps.newHashMap();
			for (Partition p : SpecialRowsInitializer.listSpecialNotIntegerCharacterRows(ps))
			{
				QuadraticInteger character1 = QuadraticFieldsInitializer.getCharacter(ps, p);
				map.put(new Pair<Partition, QuadraticInteger>(p, character1), calculateBeta(ps, p, character1));
				QuadraticInteger character2 = character1.getConjugateNumber();
				map.put(new Pair<Partition, QuadraticInteger>(p, character2), calculateBeta(ps, p, character2));
			}
			ps.setValue(BETA_MAP, map);
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static Map<Pair<Partition, QuadraticInteger>, BigInteger> getCoefficients(IPropertySource ps)
	{
		return (Map<Pair<Partition, QuadraticInteger>, BigInteger>)ps.getValue(BETA_MAP);
	}

	public static BigInteger getBetaCoefficient(IPropertySource ps, Partition partition, QuadraticInteger character)
	{
		return getCoefficients(ps).get(new Pair<Partition, QuadraticInteger>(partition, character));
	}

}
